﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PaperRenderingInterfaces;
using System.ComponentModel.Composition;
using DeepZoomPivotConstructor.PivotLib;
using HtmlAgilityPack;
using PaperPluginUtilities;

namespace CDFPreliminaryResults
{
    /// <summary>
    /// Scan a main CDF physics result index page and try to come up with
    /// the html pages that should be scanned in order to look for
    /// plots.
    /// </summary>
    [Export(typeof(IPaperRender))]
    [PaperRender("CDFPrelimIndexPage")]
    public class ScanBasicCDFIndexPage : IPaperRender
    {
        [Import]
        IWebAccess WebGetter;

        [Import]
        IPaperRenderEngine MyPaperEngine;

        /// <summary>
        /// Fetch the index apge, sort out the various links, and get renders of those.
        /// </summary>
        /// <param name="renderAddress"></param>
        /// <returns></returns>
        public IEnumerable<PivotImage> Render(string renderAddress)
        {
            ///
            /// Fetch the page and load it in as an html document.
            /// 

            Uri mainIndexPage = new Uri(renderAddress);
            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(WebGetter.GetUriAsString(mainIndexPage));

            ///
            /// Next task is to go after the main tables in here
            /// 

            var tables = new EnumerableWrapper<HtmlNode>(doc.DocumentNode.SelectNodes("//table"));
            var images = tables.SelectMany(t =>
            {
                var fixedt = t.FixUpTableHtml();
                return fixedt.ScanSubNodes("tr").SelectMany(tr => ScanTableRow(tr, mainIndexPage));
            });

            return images;
        }

        private struct LinkInfo
        {
            public Uri lnk;
            public string text;
        }

        /// <summary>
        /// Scans a single row of a table and if it is a prelim result attempts to return everything
        /// associated with it.
        /// </summary>
        /// <param name="t"></param>
        /// <param name="mainIndexPage"></param>
        /// <returns></returns>
        private IEnumerable<PivotImage> ScanTableRow(HtmlNode t, Uri baseUri)
        {
            ///
            /// Make sure there are at least 3 columns to distinguish between "empty" tables and real tables
            /// 

            if (t.ScanSubNodes("td").Count() < 3)
            {
                return Enumerable.Empty<PivotImage>();
            }

            ///
            /// Collect all links we can find here
            /// 

            var links = t.ScanSubNodes("a").Where(l => l.Attributes["href"] != null).Where(l => !l.Attributes["href"].Value.StartsWith("mail")).Select(link =>
                {
                    return new LinkInfo() { lnk = new Uri(baseUri, link.Attributes["href"].Value), text = link.InnerText.CleanHTMLText() };
                });

            ///
            /// Scan for links which indicate the info on this row has been published!
            /// 

            var isPublished = links.Any(l => l.lnk.DnsSafeHost.Contains("aps.org") || l.lnk.DnsSafeHost.Contains("aip.org"));
            var hasConfNote = links.Any(l => l.lnk.DnsSafeHost == "www-cdf.fnal.gov" && isDocument(l.lnk));
            if (isPublished && !hasConfNote)
            {
                return Enumerable.Empty<PivotImage>();
            }

            ///
            /// Next, see if we can't figure out which links are to real cdf stuff
            /// 

            var linksToGoodCDFWebPages = from l in links
                                         where l.lnk.DnsSafeHost == "www-cdf.fnal.gov" && LinkIsToPage(l.lnk)
                                         select l;

            ///
            /// Ok - now submit the remaining links to the rendering in order to get htem all "done".
            /// 

            return linksToGoodCDFWebPages.SelectMany(l =>
                MyPaperEngine.Render("HTMLPlotPage", l.lnk.OriginalString)
                .Apply(img =>
                {
                    if (!img.Any(md => md.Name == "Note Title"))
                    {
                        img.Add("Note Title", l.text);
                    }
                })
                );
        }

        string[] someFileTypes = new string[] { ".eps", ".gif", ".png", ".ps", ".pdf", ".jpg", ".jpeg", ".C", ".cpp", ".c", ".cxx", ".h", ".hxx" };

        /// <summary>
        /// Make sure the link we are looking at is going to point us to a page of some sort, not a pDF< etc.
        /// </summary>
        /// <param name="uri"></param>
        /// <returns></returns>
        private bool LinkIsToPage(Uri uri)
        {
            string lastSegment = uri.Segments.Last();
            if (!lastSegment.Contains("."))
            {
                return true;
            }

            return !isDocument(uri) && someFileTypes.All(ft => !lastSegment.EndsWith(ft));
        }

        /// <summary>
        /// Is this link pointing to a document of some sort?
        /// </summary>
        /// <param name="u"></param>
        /// <returns></returns>
        private bool isDocument(Uri u)
        {
            string lastSegment = u.Segments.Last();
            return lastSegment.Contains(".pdf") || lastSegment.Contains(".ps") || lastSegment.Contains(".ppt") || lastSegment.Contains(".pptx");
        }

    }
}
